<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>知识图谱</title>
    <meta name="description" content="" />
    <meta name="keywords" content="" />
    <meta name="author" content="" />
    <link rel="shortcut icon" href="">
    <script src="http://cdn.bootcss.com/jquery/2.1.4/jquery.min.js"></script>
    <link href="http://cdn.bootcss.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet">
    <script src="http://cdn.bootcss.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
</head>
<style type="text/css">
body {
	background-color: #ffffff;
	padding: 30px 40px;
	text-align: center;
    font-family: OpenSans-Light, PingFang SC, Hiragino Sans GB, Microsoft Yahei, Microsoft Jhenghei, sans-serif;
}

#indicator {
	position: absolute; 
	left: 60px;
	bottom: 120px;
    text-align: left;
    color: #f2f2f2;
    font-size: 12px;
}

#indicator>div {
    margin-bottom: 4px;
}

#indicator span {
    display: inline-block;
    width: 30px;
    height: 14px;
    position: relative;
    top: 2px;
    margin-right: 8px;
}

</style>
<body>

	<!-- 绘制标题样式 -->
	<h1 style="color:#fff;font-size:32px;margin-bottom:0px;text-align:center;margin-left:40px;">Star Wars</h1>

	<!-- 第一个布局 绘制知识图谱主图 -->
	<div style="text-align: center; position:relative;">
		<svg width="800" height="560" style="margin-right:80px;margin-bottom:-40px;" id="svg1">
    	</svg>

    	<!-- 绘制图例 -->
		<div id="indicator">
	    </div>

	    <!-- 绘制模式选择 -->
	    <div id="mode">
	    </div>

	    <!-- 绘制搜索框 -->
	    <div id="search">
	    </div>

	    <!-- 绘制右边显示结果 -->
	    <div id="info">
	    </div>
	</div>

	<!-- 第二个布局 下部分时间点 文本居中 相对定位-->
	<div style="text-align: center; position:relative;">
		<svg width="960" height="240" style="margin-right:60px;margin-bottom:-40px;" id="svg1">
			<g></g>
    	</svg>
	</div>

</body>

<!-- 增加D3元素库 -->
<script src="https://d3js.org/d3.v4.min.js"></script>
<!-- 补充JS代码 -->
<script type="text/javascript">
	$(document).ready(function() {
		//定义svg变量将布局svg1选出来 
		var svg = d3.select("#svg1"), 
			width = svg.attr("width"), 
			height = svg.attr("height");
		
		//定义name变量制作图标
		var names = ['Films', 'Characters', 'Planets', 'Starships', 'Vehicles', 'Species'];
		var colors = ['#6ca46c', '#4e88af', '#ca635f', '#d2907c', '#d6744d', '#ded295'];

		//背景颜色设置 补充CSS样式设置字体布局
		for (var i=0; i < names.length; i++) {
			$('#indicator').append("<div><span style='background-color:" + colors[i] + "'></span>" + names[i] + "</div>");
		}

		//利用d3.forceSimulation()定义关系图 包括设置边link、排斥电荷charge、关系图中心点
		var simulation = d3.forceSimulation()
	        .force("link", d3.forceLink().id(function(d) {
	            return d.id;
	        }))
	        .force("charge", d3.forceManyBody())
	        .force("center", d3.forceCenter(width / 2, height / 2));

	    //存储关系图的数据
	    var graph;

	    //定义d3.json请求python处理好的节点及边 请求成功返回数据，否则报错
	    d3.json("qyn.json", function(error, data) {
	    	if(error) throw error;
	    	graph = data;
	    	console.log(graph);

	    	//D3映射数据至HTML中
	    	//g用于绘制所有边,selectALL选中所有的line,并绑定数据data(graph.links),enter().append("line")添加元素
	    	//数据驱动文档,设置边的粗细
	    	var link = svg.append("g").attr("class","links").selectAll("line").data(graph.links).enter()
	    	.append("line").attr("stroke-width", function(d) {
	    		//return Math.sqrt(d.value);
	    		return 3; //所有线宽度均为1
	    	});

	    	//添加所有的点
	    	//selectAll("circle")选中所有的圆并绑定数据,圆的直径为d.size
	    	//再定义圆的填充色,同样数据驱动样式,圆没有描边,圆的名字为d.id
	    	//call()函数：拖动函数,当拖动开始绑定dragstarted函数，拖动进行和拖动结束也绑定函数
	    	var node = svg.append("g").attr("class", "nodes").selectAll("circle").data(graph.nodes).enter()
	    	.append("circle").attr("r", function(d) {
	    		return d.size;
	    	}).attr("fill", function(d) {
	    		return colors[d.group];
	    	}).attr("stroke", "none").attr("name", function(d) {
	    		return d.id;
	    	}).call(d3.drag()
	    		.on("start", dragstarted)
	    		.on("drag", dragged)
	    		.on("end", dragended)
	    	);

	    	//显示所有的文本 
	    	//设置大小、填充颜色、名字、text()设置文本
	    	//attr("text-anchor", "middle")设置文本居中
	    	var text = svg.append("g").attr("class", "texts").selectAll("text").data(graph.nodes).enter()
	    	.append("text").attr("font-size", function(d) {
                return d.size;
            }).attr("fill", function(d) {
                return colors[d.group];
            }).attr('name', function(d) {
                return d.id;
            }).text(function(d) {
                return d.id;
            }).attr('text-anchor', 'middle').call(d3.drag()
                .on("start", dragstarted)
                .on("drag", dragged)
                .on("end", dragended)
            );

	    	//圆增加title
	    	node.append("title").text(function(d) {
	    		return d.id;
	    	})
	    	
	    	//simulation中ticked数据初始化并生成图形
	    	simulation
	            .nodes(graph.nodes)
	            .on("tick", ticked);

	        simulation.force("link")
	            .links(graph.links);

	        //ticked()函数确定link线的起始点x、y坐标 node确定中心点 文本通过translate平移变化
	        function ticked() {
	            link
	                .attr("x1", function(d) {
	                    return d.source.x;
	                })
	                .attr("y1", function(d) {
	                    return d.source.y;
	                })
	                .attr("x2", function(d) {
	                    return d.target.x;
	                })
	                .attr("y2", function(d) {
	                    return d.target.y;
	                });

	            node
	                .attr("cx", function(d) {
	                    return d.x;
	                })
	                .attr("cy", function(d) {
	                    return d.y;
	                });

	            text.
	            attr('transform', function(d) {
	                return 'translate(' + d.x + ',' + (d.y + d.size / 2) + ')';
	            });
	        }
	    });


	    // Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension
	    // 本地json数据需要放置服务器中请求 XAMPP


	    //拖动函数代码
	    //var dragging = false;

	    //开始拖动并更新相应的点
	    function dragstarted(d) {
	        if (!d3.event.active) simulation.alphaTarget(0.3).restart();
	        d.fx = d.x;
	        d.fy = d.y;
	        //dragging = true;
	    }

	    //拖动进行中
	    function dragged(d) {
	        d.fx = d3.event.x;
	        d.fy = d3.event.y;
	    }

	    //拖动结束
	    function dragended(d) {
	        if (!d3.event.active) simulation.alphaTarget(0);
	        d.fx = null;
	        d.fy = null;
	        //dragging = false;
	    }

	});
</script>
</html>